﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 天机万年历.自定义控件
{

    public partial class LunarLabel : Label
    {
        public bool CustomDraw = false;
        protected override void OnPaint(PaintEventArgs e)
        {
            if (CustomDraw)
            {
                var rect = e.ClipRectangle;
                rect.X = Left;
                rect.Y = Top;
                if (Text.IndexOf("星期") == -1)
                {
                    rect.X += this.Parent.Left;
                    rect.Y += this.Parent.Top;
                }
                CustomPaint(new PaintEventArgs(e.Graphics, rect));
            }
            else
                base.OnPaint(e);
        }
        private static readonly ContentAlignment anyRight = ContentAlignment.TopRight | ContentAlignment.MiddleRight | ContentAlignment.BottomRight;
        private static readonly ContentAlignment anyBottom = ContentAlignment.BottomLeft | ContentAlignment.BottomCenter | ContentAlignment.BottomRight;
        private static readonly ContentAlignment anyCenter = ContentAlignment.TopCenter | ContentAlignment.MiddleCenter | ContentAlignment.BottomCenter;
        private static readonly ContentAlignment anyMiddle = ContentAlignment.MiddleLeft | ContentAlignment.MiddleCenter | ContentAlignment.MiddleRight;
        static StringAlignment TranslateAlignment(ContentAlignment align)
        {
            StringAlignment result;
            if ((align & anyRight) != 0)
                result = StringAlignment.Far;
            else if ((align & anyCenter) != 0)
                result = StringAlignment.Center;
            else
                result = StringAlignment.Near;
            return result;
        }
        static StringAlignment TranslateLineAlignment(ContentAlignment align)
        {
            StringAlignment result;
            if ((align & anyBottom) != 0)
            {
                result = StringAlignment.Far;
            }
            else if ((align & anyMiddle) != 0)
            {
                result = StringAlignment.Center;
            }
            else
            {
                result = StringAlignment.Near;
            }
            return result;
        }
        static StringFormat StringFormatForAlignment(ContentAlignment align)
        {
            StringFormat output = new StringFormat();
            output.Alignment = TranslateAlignment(align);
            output.LineAlignment = TranslateLineAlignment(align);
            return output;
        }
        static StringFormat CreateStringFormat(Control ctl, ContentAlignment textAlign, bool showEllipsis, bool useMnemonic)
        {

            StringFormat stringFormat = StringFormatForAlignment(textAlign);

            // make sure that the text is contained within the label
            // 


            // Adjust string format for Rtl controls
            if (ctl.RightToLeft == RightToLeft.Yes)
            {
                stringFormat.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
            }

            if (showEllipsis)
            {
                stringFormat.Trimming = StringTrimming.EllipsisCharacter;
                stringFormat.FormatFlags |= StringFormatFlags.LineLimit;
            }

            if (!useMnemonic)
            {
                stringFormat.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.None;
            }
            //else if (ctl.ShowKeyboardCues)
            //{
            //    stringFormat.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show;
            //}
            else
            {
                stringFormat.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Hide;
            }

            if (ctl.AutoSize)
            {
                stringFormat.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
            }

            return stringFormat;
        }
        static bool IsDarker(Color c1, Color c2)
        {
            HLSColor hc1 = new HLSColor(c1);
            HLSColor hc2 = new HLSColor(c2);
            return (hc1.Luminosity < hc2.Luminosity);
        }
        static Color DisabledTextColor(Color backColor)
        {
            //Theme specs -- if the backcolor is darker than Control, we use
            // ControlPaint.Dark(backcolor).  Otherwise we use ControlDark.
            // see VS#357226
            Color disabledTextForeColor = SystemColors.ControlDark;
            if (IsDarker(backColor, SystemColors.Control))
            {
                disabledTextForeColor = ControlPaint.Dark(backColor);
            }
            return disabledTextForeColor;
        }
        public void CustomPaint(Graphics g)
        {
            var rect = this.ClientRectangle;
            rect.X = Left;
            rect.Y = Top;
            if (Text.IndexOf("星期") == -1)
            {
                rect.X += this.Parent.Left;
                rect.Y += this.Parent.Top;
            }
            CustomPaint(new PaintEventArgs(g, rect));
        }
        void CustomPaint(PaintEventArgs e)
        {
            if (!Parent.Visible)
                return;
            //ImageAnimator.UpdateFrames(this.Image);

            Rectangle face = e.ClipRectangle;
            Image i = this.Image;
            if (i != null)
            {
                DrawImage(e.Graphics, i, face, RtlTranslateAlignment(ImageAlign));
            }

            Color color;
            IntPtr hdc = e.Graphics.GetHdc();

            try
            {
                //using (WindowsGraphics wg = WindowsGraphics.FromHdc(hdc))
                {
                    //color = wg.GetNearestColor((Enabled) ? ForeColor : DisabledColor);
                    color = ForeColor;
                }
            }
            finally
            {
                e.Graphics.ReleaseHdc();
            }

            // Do actual drawing

            if (AutoEllipsis)
            {
                Rectangle clientRect = this.ClientRectangle;
                Size preferredSize = GetPreferredSize(new Size(clientRect.Width, clientRect.Height));
                //ShowToolTip = (clientRect.Width < preferredSize.Width || clientRect.Height < preferredSize.Height);
            }
            else
            {
                //showToolTip = false;
            }

            if (UseCompatibleTextRendering)
            {
                using (StringFormat stringFormat = CreateStringFormat(this, this.TextAlign, this.AutoEllipsis, this.UseMnemonic))
                {
                    if (Enabled)
                    {
                        using (Brush brush = new SolidBrush(color))
                        {
                            e.Graphics.DrawString(Text, Font, brush, face, stringFormat);
                        }
                    }
                    else
                    {
                        ControlPaint.DrawStringDisabled(e.Graphics, Text, Font, color, face, stringFormat);
                    }
                }
            }
            else
            {
                TextFormatFlags flags = TextFormatFlags.HorizontalCenter;// CreateTextFormatFlags();

                if (Enabled)
                {
                    TextRenderer.DrawText(e.Graphics, Text, Font, face, color, flags);
                }
                else
                {
                    //Theme specs -- if the backcolor is darker than Control, we use
                    // ControlPaint.Dark(backcolor).  Otherwise we use ControlDark.
                    // see VS#357226
                    Color disabledTextForeColor = DisabledTextColor(this.BackColor);
                    TextRenderer.DrawText(e.Graphics, Text, Font, face, disabledTextForeColor, flags);
                }
            }
        }
        private TextFormatFlags CreateTextFormatFlags()
        {
            return CreateTextFormatFlags(this.Size - GetBordersAndPadding());
        }
        Size GetBordersAndPadding()
        {
            Size bordersAndPadding = Padding.Size;

            // COMPAT VSW 248415: Everett added random numbers to the height of the label               
            if (UseCompatibleTextRendering)
            {
                //Always return the Fontheight + some buffer else the Text gets clipped for Autosize = true..
                //(bug 118909)
                if (BorderStyle != BorderStyle.None)
                {
                    bordersAndPadding.Height += 6; // taken from Everett.PreferredHeight
                    bordersAndPadding.Width += 2; // taken from Everett.PreferredWidth
                }
                else
                {
                    bordersAndPadding.Height += 3; // taken from Everett.PreferredHeight
                }
            }
            else
            {
                // in Whidbey we'll actually ask the control the border size.

                bordersAndPadding += SizeFromClientSize(Size.Empty);
                if (BorderStyle == BorderStyle.Fixed3D)
                {
                    bordersAndPadding += new Size(2, 2);
                }
            }
            return bordersAndPadding;

        }
        static TextFormatFlags TextFormatFlagsForAlignmentGDI(ContentAlignment align)
        {
            TextFormatFlags output = new TextFormatFlags();
            output |= TranslateAlignmentForGDI(align);
            output |= TranslateLineAlignmentForGDI(align);
            return output;
        }
        static TextFormatFlags TranslateLineAlignmentForGDI(ContentAlignment align)
        {
            TextFormatFlags result;
            if ((align & anyRight) != 0)
                result = TextFormatFlags.Right;
            else if ((align & anyCenter) != 0)
                result = TextFormatFlags.HorizontalCenter;
            else
                result = TextFormatFlags.Left;
            return result;
        }
        static TextFormatFlags TranslateAlignmentForGDI(ContentAlignment align)
        {
            TextFormatFlags result;
            if ((align & anyBottom) != 0)
                result = TextFormatFlags.Bottom;
            else if ((align & anyMiddle) != 0)
                result = TextFormatFlags.VerticalCenter;
            else
                result = TextFormatFlags.Top;
            return result;
        }
        TextFormatFlags CreateTextFormatFlags(Control ctl, ContentAlignment textAlign, bool showEllipsis, bool useMnemonic)
        {

            textAlign = this.RtlTranslateContent(textAlign);
            TextFormatFlags flags = TextFormatFlagsForAlignmentGDI(textAlign);

            // The effect of the TextBoxControl flag is that in-word line breaking will occur if needed, this happens when AutoSize 
            // is false and a one-word line still doesn't fit the binding box (width).  The other effect is that partially visible 
            // lines are clipped; this is how GDI+ works by default.
            flags |= TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl;

            if (showEllipsis)
            {
                flags |= TextFormatFlags.EndEllipsis;
            }

            // Adjust string format for Rtl controls
            if (ctl.RightToLeft == RightToLeft.Yes)
            {
                flags |= TextFormatFlags.RightToLeft;
            }

            //if we don't use mnemonic, set formatFlag to NoPrefix as this will show the ampersand
            if (!useMnemonic)
            {
                flags |= TextFormatFlags.NoPrefix;
            }
            //else if we don't show keyboard cues, set formatFlag to HidePrefix as this will hide
            //the ampersand if we don't press down the alt key
            //else if (!ctl.ShowKeyboardCues)
            //{
            //    flags |= TextFormatFlags.HidePrefix;
            //}

            return flags;
        }
        TextFormatFlags CreateTextFormatFlags(Size constrainingSize)
        {

            // PREFERRED SIZE CACHING: 
            // Please read if you're adding a new TextFormatFlag.
            // whenever something can change the TextFormatFlags used
            // MeasureTextCache.InvalidateCache() should be called so we can approprately clear.

            TextFormatFlags flags = CreateTextFormatFlags(this, this.TextAlign, this.AutoEllipsis, this.UseMnemonic);

            // Remove WordBreak if the size is large enough to display all the text.
            //if (!MeasureTextCache.TextRequiresWordBreak(Text, Font, constrainingSize, flags))
            {
                // The effect of the TextBoxControl flag is that in-word line breaking will occur if needed, this happens when AutoSize 
                // is false and a one-word line still doesn't fit the binding box (width).  The other effect is that partially visible 
                // lines are clipped; this is how GDI+ works by default.
                //flags &= ~(TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl);
            }

            return flags;
        }
    }
}
